/*****************************************************************************
*    Copyright (C) 2008 ALi Corp. All Rights Reserved.
*    
*    Company confidential and Properietary information.       
*    This information may not be disclosed to unauthorized  
*    individual.    
*    File: win_net_upg.c
*   
*    Description: 
*    
*    History: 
*    Date           Athor        Version        Reason
*    ========       ========     ========       ========
*    2008/12/4      Roman        1.0.0			Create   
*        
*****************************************************************************/
#include <sys_config.h>

#ifdef NETWORK_SUPPORT
#include <types.h>
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <osal/osal.h>
#ifndef NEW_DEMO_FRAME
#include <api/libpub29/lib_pub27.h>
#include <api/libpub29/lib_as.h>
#endif
#include <api/libosd/osd_lib.h>

#include "osdobjs_def.h"
#include "string.id"
#include "images.id"
#include "osd_config.h"

#include "menus_root.h"
#include "win_com.h"
#include "win_com_popup.h"
#include "win_com_list.h"
#include "win_signalstatus.h"
#include "win_com_menu_define.h"
#include "mobile_input.h"

#include <hal/hal_gpio.h>
#include <api/libchunk/chunk.h>
#include <hld/sto/sto_dev.h>
#include <api/libnet/libnet.h>
#include <api/libtcpip/lwip/inet.h>
#include <api/libupg/net_upgrade.h>
#include <api/libchunk/chunk.h>

/*******************************************************************************
*   Objects definition
*******************************************************************************/
extern CONTAINER g_win_netupg;

extern CONTAINER netupg_item_con1;
extern CONTAINER netupg_item_con2;
extern CONTAINER netupg_item_con3;
extern CONTAINER netupg_item_con4;
extern CONTAINER netupg_item_con5;
extern CONTAINER netupg_item_con6;

extern TEXT_FIELD netupg_item_txtname1;
extern TEXT_FIELD netupg_item_txtname2;
extern TEXT_FIELD netupg_item_txtname3;
extern TEXT_FIELD netupg_item_txtname4;
extern TEXT_FIELD netupg_item_txtname5;
extern TEXT_FIELD netupg_item_txtname6;

extern MULTISEL netupg_item_tcpip_type;
extern MULTISEL netupg_item_url_type;
extern EDIT_FIELD netupg_item_url;
extern EDIT_FIELD netupg_item_user;
extern EDIT_FIELD netupg_item_pwd;
extern MULTISEL netupg_item_txtset5;
extern MULTISEL netupg_item_txtset6;

extern CONTAINER netupg_info_con;
extern TEXT_FIELD netupg_txt_progress;
extern PROGRESS_BAR netupg_bar_progress;
extern TEXT_FIELD netupg_txt_msg;

extern TEXT_FIELD netupg_item_line1;
extern TEXT_FIELD netupg_item_line2;
extern TEXT_FIELD netupg_item_line3;
extern TEXT_FIELD netupg_item_line4;
extern TEXT_FIELD netupg_item_line5;
extern TEXT_FIELD netupg_item_line6;

static VACTION netupg_item_sel_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT netupg_item_sel_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static VACTION  netupg_item_edf_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT  netupg_item_edf_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static VACTION netupg_item_con_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT netupg_item_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static VACTION netupg_con_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT netupg_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static PRESULT	netupg_msg_proc(UINT32 msg_type, UINT32 msg_code);

static UINT16 protocol_type[];
static UINT16 url_type[];

#define NETUPG_MSG_MAX_LINE 2
static char netupg_msg_buf[NETUPG_MSG_MAX_LINE+1][64];
static UINT32 netupg_msg_line;

#define WIN_SH_IDX    WSTL_WIN_BODYRIGHT_01_HD

#define CON_SH_IDX   WSTL_BUTTON_01_HD
#define CON_HL_IDX   WSTL_BUTTON_05_HD
#define CON_SL_IDX   WSTL_BUTTON_01_HD
#define CON_GRY_IDX  WSTL_BUTTON_07_HD

#define TXT_SH_IDX   WSTL_BUTTON_01_FG_HD
#define TXT_HL_IDX   WSTL_BUTTON_02_FG_HD
#define TXT_SL_IDX   WSTL_BUTTON_01_FG_HD
#define TXT_GRY_IDX  WSTL_BUTTON_07_HD

#define SEL_SH_IDX   WSTL_BUTTON_01_FG_HD
#define SEL_HL_IDX   WSTL_BUTTON_04_HD
#define SEL_SL_IDX   WSTL_BUTTON_01_FG_HD
#define SEL_GRY_IDX  WSTL_BUTTON_07_HD

#define EDF_SH_IDX   WSTL_BUTTON_01_FG_HD
#define EDF_HL_IDX   WSTL_BUTTON_04_HD
#define EDF_SL_IDX   WSTL_BUTTON_01_FG_HD
#define EDF_GRY_IDX  WSTL_BUTTON_07_HD

#define PROGRESSBAR_SH_IDX			WSTL_BARBG_01_HD
#define PROGRESSBAR_MID_SH_IDX		WSTL_NOSHOW_IDX
#define PROGRESSBAR_PROGRESS_SH_IDX	WSTL_BAR_04_HD
#define PROGRESS_TXT_SH_IDX	WSTL_BUTTON_01_HD

#define MSG_SH_IDX WSTL_TEXT_09_HD//WSTL_TEXT_04_HD
#define UPG_INFO_SH_IDX	WSTL_TEXT_09_HD

#define TXT_L_OF  	TXTN_L_OF
#define TXT_W  		TXTN_W
#define TXT_H		TXTN_H
#define TXT_T_OF	TXTN_T_OF

#define SEL_L_OF 	TXTS_L_OF
#define SEL_W  		TXTS_W
#define SEL_H		TXTS_H
#define SEL_T_OF	TXTS_T_OF

#define BAR_L	(CON_L+5)
#define BAR_T	(CON_T + (CON_H + CON_GAP)*6+10)
#define BAR_W	(CON_W-BAR_TXT_W-10)
#define BAR_H	24

#define BAR_TXT_L (BAR_L + BAR_W + 6)
#define BAR_TXT_W	100//sharon 60
#define BAR_TXT_T ( BAR_T - 6)
#define BAR_TXT_H	36//24 

#define MSG_L	(CON_L+5)
#define MSG_T	(BAR_T + BAR_H+20)
#define MSG_W	(CON_W-10)
#define MSG_H	36
#define MSG_GAP	4

enum
{
    IDC_NETUPG_TYPE = 1,
	IDC_NETUPG_URL_TYPE,
    IDC_NETUPG_URL,
    IDC_NETUPG_USER,
    IDC_NETUPG_PASSWORD,
    IDC_NETUPG_START,
};

#define LDEF_CON(root, varCon,nxtObj,ID,IDl,IDr,IDu,IDd,l,t,w,h,conobj,focusID)     \
    DEF_CONTAINER(varCon,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,IDl,IDr,IDu,IDd, l,t,w,h, CON_SH_IDX,CON_HL_IDX,CON_SL_IDX,CON_GRY_IDX,   \
    netupg_item_con_keymap,netupg_item_con_callback,  \
    conobj, focusID,1)

#define LDEF_TXT(root,varTxt,nxtObj,l,t,w,h,resID)      \
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, TXT_SH_IDX,TXT_HL_IDX,TXT_SL_IDX,TXT_GRY_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,resID,NULL)

#define LDEF_EDIT(root, varNum, nxtObj, ID, l, t, w, h,style,max_len,cursormode,pat,pre,sub,str)	\
    DEF_EDITFIELD(varNum,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,ID,ID,ID,ID, l,t,w,h, EDF_SH_IDX,EDF_HL_IDX,EDF_SL_IDX,EDF_GRY_IDX,   \
    netupg_item_edf_keymap,netupg_item_edf_callback,  \
    C_ALIGN_CENTER | C_ALIGN_VCENTER, 20,0,style,pat,max_len,cursormode,pre,sub,str)

#define LDEF_MSEL(root, varNum, nxtObj, ID, l, t, w, h,style,cur,cnt,ptabl) \
    DEF_MULTISEL(varNum,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,ID,ID,ID,ID, l,t,w,h, SEL_SH_IDX,SEL_HL_IDX,SEL_SL_IDX,SEL_GRY_IDX,   \
    netupg_item_sel_keymap,netupg_item_sel_callback,  \
    C_ALIGN_CENTER | C_ALIGN_VCENTER, 20,0,style,ptabl,cur,cnt)

#define LDEF_EDIT_MENU_ITEM(root,varCon,nxtObj,varTxt,varNum,varLine,ID,IDu,IDd,l,t,w,h,\
                        resID,style,max_len,cursormode,pat,pre,sub,str) \
    LDEF_CON(&root,varCon,nxtObj,ID,ID,ID,IDu,IDd,l,t,w,h,&varTxt,ID)   \
    LDEF_TXT(&varCon,varTxt,&varNum,l + TXT_L_OF,t + TXT_T_OF,TXT_W,TXT_H,resID)    \
    LDEF_EDIT(&varCon,varNum,NULL/*&varLine*/   ,ID,l + SEL_L_OF ,t + SEL_T_OF,SEL_W,SEL_H,style,max_len,cursormode,pat,pre,sub,str)\
    LDEF_LINE(&varCon,varLine,NULL,1,1,1,1,1,l + LINE_L_OF, t + LINE_T_OF,LINE_W,LINE_H,0,0)

#define LDEF_SEL_MENU_ITEM(root,varCon,nxtObj,varTxt,varNum,varLine,ID,IDu,IDd,l,t,w,h,\
                        resID,style,cur,cnt,ptbl) \
    LDEF_CON(&root,varCon,nxtObj,ID,ID,ID,IDu,IDd,l,t,w,h,&varTxt,ID)   \
    LDEF_TXT(&varCon,varTxt,&varNum,l + TXT_L_OF,t + TXT_T_OF,TXT_W,TXT_H,resID)    \
    LDEF_MSEL(&varCon,varNum,NULL/*&varLine*/   ,ID, l + SEL_L_OF ,t + SEL_T_OF,SEL_W,SEL_H,style,cur,cnt,ptbl)\
    LDEF_LINE(&varCon,varLine,NULL,1,1,1,1,1,l + LINE_L_OF, t + LINE_T_OF,LINE_W,LINE_H,0,0)

#define LDEF_TXT_MENU_ITEM(root,varCon,nxtObj,varTxt,varLine,ID,IDu,IDd,l,t,w,h,resID) \
    LDEF_CON(&root,varCon,nxtObj,ID,ID,ID,IDu,IDd,l,t,w,h,&varTxt,ID)   \
    LDEF_TXT(&varCon,varTxt,NULL/*&varLine*/,l + TXT_L_OF,t + TXT_T_OF,TXT_W,TXT_H,resID)\
    LDEF_LINE(&varCon,varLine,NULL,1,1,1,1,1,l + LINE_L_OF, t + LINE_T_OF,LINE_W,LINE_H,0,0)

#define LDEF_INFOCON(varCon,nxtObj,l,t,w,h)		\
    DEF_CONTAINER(varCon,NULL,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, UPG_INFO_SH_IDX,UPG_INFO_SH_IDX,UPG_INFO_SH_IDX,UPG_INFO_SH_IDX,   \
    NULL,NULL,  \
    &nxtObj, 0,0)

#define LDEF_PROGRESS_BAR(root,varBar,nxtObj,l,t,w,h,style,rl,rt,rw,rh)	\
	DEF_PROGRESSBAR(varBar, &root, nxtObj, C_ATTR_ACTIVE, 0, \
		0, 0, 0, 0, 0, l, t, w, h, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX,\
		NULL, NULL, style, 0, 0, PROGRESSBAR_MID_SH_IDX, PROGRESSBAR_PROGRESS_SH_IDX, \
		rl,rt , rw, rh, 1, 100, 100, 0)
   
#define LDEF_PROGRESS_TXT(root,varTxt,nxtObj,l,t,w,h)		\
    DEF_TEXTFIELD(varTxt,&root,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, PROGRESS_TXT_SH_IDX,PROGRESS_TXT_SH_IDX,PROGRESS_TXT_SH_IDX,PROGRESS_TXT_SH_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,0,display_strs[6])

#define LDEF_TXT_MSG(root,varTxt)		\
    DEF_TEXTFIELD(varTxt,&root,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0,  0,0,0,0, MSG_SH_IDX,0,0,0,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,0,display_strs[7])

#define LDEF_WIN(varCon,nxtObj,l,t,w,h,focusID)     \
    DEF_CONTAINER(varCon,NULL,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,   \
    netupg_con_keymap,netupg_con_callback,  \
    nxtObj, focusID,0)

static char ip_pattern[] = "i00";
static char string_pattern[] = "s17";
static char pwd_pattern[] = "m-*15";

LDEF_SEL_MENU_ITEM(g_win_netupg,netupg_item_con1, &netupg_item_con2,netupg_item_txtname1,netupg_item_tcpip_type,netupg_item_line1,1,6,2,   \
                CON_L, CON_T + (CON_H + CON_GAP)*0,CON_W,CON_H, RS_NET_PROTOCOL,\
                STRING_ID,0,2,protocol_type)

LDEF_SEL_MENU_ITEM(g_win_netupg,netupg_item_con2, &netupg_item_con3,netupg_item_txtname2,netupg_item_url_type,netupg_item_line2,2,1,3,   \
                CON_L, CON_T + (CON_H + CON_GAP)*1,CON_W,CON_H, RS_NET_URL_TYPE,\
                STRING_ID,0,2,url_type)

LDEF_EDIT_MENU_ITEM(g_win_netupg,netupg_item_con3, &netupg_item_con4,netupg_item_txtname3,netupg_item_url,netupg_item_line3,3,2,4,    \
                CON_L, CON_T + (CON_H + CON_GAP)*2,CON_W,CON_H, RS_NET_URL,\
                NORMAL_EDIT_MODE,MAX_URL_LEN,CURSOR_NORMAL,string_pattern,NULL,NULL,display_strs[0])

LDEF_EDIT_MENU_ITEM(g_win_netupg,netupg_item_con4, &netupg_item_con5,netupg_item_txtname4,netupg_item_user,netupg_item_line4,4,3,5,  \
                CON_L, CON_T + (CON_H + CON_GAP)*3,CON_W,CON_H, RS_INFO_LNB_USER,\
                NORMAL_EDIT_MODE,MAX_IP_USER_NAME,CURSOR_NORMAL,string_pattern,NULL,NULL,display_strs[1])

LDEF_EDIT_MENU_ITEM(g_win_netupg,netupg_item_con5, &netupg_item_con6,netupg_item_txtname5,netupg_item_pwd,netupg_item_line5,5,4,6,    \
                CON_L, CON_T + (CON_H + CON_GAP)*4,CON_W,CON_H, RS_NET_PASSWORD,\
                NORMAL_EDIT_MODE,MAX_IP_PWD_LEN,CURSOR_NORMAL,pwd_pattern,NULL,NULL,display_strs[2])

LDEF_TXT_MENU_ITEM(g_win_netupg,netupg_item_con6, &netupg_info_con,netupg_item_txtname6,netupg_item_line6,6,5,1,    \
                CON_L, CON_T + (CON_H + CON_GAP)*5,CON_W,CON_H, RS_COMMON_START)

LDEF_INFOCON(netupg_info_con, netupg_bar_progress,CON_L,CON_T + (CON_H + CON_GAP)*6, CON_W, 150)

LDEF_PROGRESS_BAR(netupg_info_con,netupg_bar_progress,&netupg_txt_progress,	\
	BAR_L, BAR_T, BAR_W, BAR_H, PROGRESSBAR_HORI_NORMAL | PBAR_STYLE_RECT_STYLE,2,5,BAR_W,BAR_H-10) ///// 2,5,B_W,B_H-10,0

LDEF_PROGRESS_TXT(netupg_info_con, netupg_txt_progress, NULL, \
		BAR_TXT_L, BAR_TXT_T, BAR_TXT_W, BAR_TXT_H)

LDEF_TXT_MSG(netupg_info_con,netupg_txt_msg)

LDEF_WIN(g_win_netupg,&netupg_item_con1,W_L, W_T, W_W, W_H, 1)


/*******************************************************************************
*   Local functions & variables define
*******************************************************************************/
static UINT16 protocol_type[] = 
{
	RS_NET_HTTP,
	RS_NET_FTP,
};
static UINT16 url_type[] = 
{
	RS_NET_URL_TYPE_INT,
	RS_NET_URL_TYPE_STRING,
};

static struct help_item_resource  netupg_helpinfo[] =
{
    {IM_EPG_COLORBUTTON_RED,       RS_COM_CAPS},
    {IM_EPG_COLORBUTTON_GREEN,     RS_HELP_DELETE},
    {IM_EPG_COLORBUTTON_YELLOW,    RS_NET_ABORT},
};

static POBJECT_HEAD netupg_objs[] = 
{
	(POBJECT_HEAD)&netupg_item_tcpip_type,
	(POBJECT_HEAD)&netupg_item_url,
	(POBJECT_HEAD)&netupg_item_user,
	(POBJECT_HEAD)&netupg_item_pwd,
};

static IP_REMOTE_CFG net_remote_cfg;
static UINT8 use_last_ip_cfg;

static int download_started = 0;
static UINT32 upgrade_handle = 0; // used to abort download
static UINT32 net_file_type;  //0 - config file, 1 - upgrade abs file
static UINT32 net_file_length; //the file length of the download file 

#define DEFULT_CONFIG_FILE "download_setting.cfg"

static UINT8* buffer_for_cfgfile = (UINT8*)(__MM_PVR_VOB_BUFFER_ADDR&0x0fffffff|0x80000000);
static UINT32 buflen_for_cfgfile = 512 * 1024;
static UINT8* buffer_for_upgradefile =  (UINT8*)((__MM_PVR_VOB_BUFFER_ADDR&0x0fffffff|0x80000000) + 1024 * 1024);
static UINT32 buflen_for_upgradefile = 8 * 1024 * 1024;

static void net_mi_callback(UINT8* string);
static int  network_performance_test = 0;
static mobile_input_type_t mit_normal = 
{
	MOBILE_INPUT_NORMAL,
	MOBILE_CAPS_INIT_LOW,
	17,
	0,
	net_mi_callback,
};

static mobile_input_type_t mit_pwd = 
{
	MOBILE_INPUT_PWD,
	MOBILE_CAPS_INIT_LOW,
	17,
	0,
	net_mi_callback,
};

static void netupg_mobile_input_init(UINT8 id)
{
	mobile_input_init(&netupg_item_pwd, NULL);
}


static void win_netupg_process_update(UINT32 process)
{

	if(process > 100)
		process = 0;

	OSD_SetProgressBarPos(&netupg_bar_progress,(INT16)process);
	OSD_SetTextFieldContent(&netupg_txt_progress, STRING_NUM_PERCENT, (UINT32)process);

	OSD_DrawObject( (POBJECT_HEAD)&netupg_bar_progress, C_UPDATE_ALL);
	OSD_DrawObject( (POBJECT_HEAD)&netupg_txt_progress, C_UPDATE_ALL);
}

static void win_netupg_msg_update(const char *msg)
{
	UINT32 i,j;
	OSD_RECT rect;

	//ComAscStr2Uni(str, display_strs[10+usbupg_msg_line%USBUPG_MSG_MAX_LINE]);
	if(NETUPG_MSG_MAX_LINE == netupg_msg_line)
	{
		for(i = 0; i < NETUPG_MSG_MAX_LINE - 1; i++)
			STRCPY(netupg_msg_buf[i], netupg_msg_buf[i + 1]);
		STRCPY(netupg_msg_buf[i], (char *)msg);
	}
	else
	{
		STRCPY(netupg_msg_buf[netupg_msg_line++], (char *)msg);
	}
	

	//draw msg infos
	for(i=0; i<NETUPG_MSG_MAX_LINE; i++)
	{
		rect.uLeft 	= MSG_L;
		rect.uTop  	= MSG_T+(MSG_H+MSG_GAP)*i;
		rect.uWidth = MSG_W;
		rect.uHeight= MSG_H;

		OSD_SetRect2(&netupg_txt_msg.head.frame, &rect);
		OSD_SetTextFieldContent(&netupg_txt_msg, STRING_ANSI, (UINT32)netupg_msg_buf[i]);
		OSD_DrawObject( (POBJECT_HEAD)&netupg_txt_msg, C_UPDATE_ALL);
	}
}

static void win_netupg_msg_clear()
{
	UINT8 i;
	OSD_RECT rect;
	
	for(i=0;i<NETUPG_MSG_MAX_LINE;i++)
	{
		netupg_msg_buf[i][0] = 0;

		rect.uLeft 	= MSG_L;
		rect.uTop  	= MSG_T+(MSG_H+MSG_GAP)*i;
		rect.uWidth = MSG_W;
		rect.uHeight= MSG_H;

		OSD_SetRect2(&netupg_txt_msg.head.frame, &rect);
		OSD_SetTextFieldContent(&netupg_txt_msg, STRING_ANSI, (UINT32)netupg_msg_buf[i]);
		OSD_DrawObject( (POBJECT_HEAD)&netupg_txt_msg, C_UPDATE_ALL);
	}

 	netupg_msg_line = 0;	
}


static void netupg_set_url(BOOL update)
{
	if(net_remote_cfg.url_type == 0)
	{	
		// url type is ip address, change to ip pattern
		OSD_SetEditFieldPattern(&netupg_item_url,ip_pattern);
		OSD_SetEditFieldContent(&netupg_item_url, STRING_NUMBER, ntohl(net_remote_cfg.url_int));
	}
	else
	{
		// url type is string, change to string pattern and enable mobile input.
		OSD_SetEditFieldPattern(&netupg_item_url,string_pattern);
		OSD_SetEditFieldContent(&netupg_item_url, STRING_ANSI, (UINT32)net_remote_cfg.url_str);
	}
	if(update)
		OSD_DrawObject((POBJECT_HEAD)&netupg_item_con3,C_UPDATE_ALL);
}

static void netupg_sel_protocol(UINT32 protocol, BOOL update)
{
	UINT32 nCmdDraw = C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL;
	UINT8 action = (protocol == 0) ? C_ATTR_INACTIVE : C_ATTR_ACTIVE; // 0: http
	set_container_active(&netupg_item_con4, action); /* User */
	set_container_active(&netupg_item_con5, action); /* Password */

	if (update)
	{		
		OSD_DrawObject((POBJECT_HEAD)&netupg_item_con4, nCmdDraw);
		OSD_DrawObject((POBJECT_HEAD)&netupg_item_con5, nCmdDraw);
	}
}

static void netupg_init()
{
	UINT16 block_cnt;

	//init the blocks
	netupg_block_free();
	netupg_block_init(&block_cnt);

	// get last remote setting.
	use_last_ip_cfg = get_ip_cfg_last_active();

	if(use_last_ip_cfg)
		get_remote_ip_cfg(&net_remote_cfg);
	else
		get_remote_ip_dft_cfg(&net_remote_cfg);

	// set the tcpip type
	OSD_SetMultiselSel(&netupg_item_tcpip_type, net_remote_cfg.protocol_type);

	netupg_sel_protocol(net_remote_cfg.protocol_type, FALSE);

	// set the url type
	OSD_SetMultiselSel(&netupg_item_url_type, net_remote_cfg.url_type);

	// set the url
	netupg_set_url(FALSE);
	
	// user is alway have mobile input type.
	OSD_SetEditFieldContent(&netupg_item_user, STRING_ANSI, (UINT32)net_remote_cfg.user);

	// to support any key password, it must be mobile input type.
	OSD_SetEditFieldContent(&netupg_item_pwd, STRING_ANSI, (UINT32)net_remote_cfg.pwd);

	OSD_SetProgressBarPos(&netupg_bar_progress,(INT16)0);
	OSD_SetTextFieldContent(&netupg_txt_progress, STRING_NUM_PERCENT, (UINT32)0);
	OSD_SetContainerFocus(&g_win_netupg,IDC_NETUPG_TYPE);
	netupg_mobile_input_init(IDC_NETUPG_URL);
}

static void win_get_netupg_param()
{
	UINT32 value;

	// get protocol type
	net_remote_cfg.protocol_type = OSD_GetMultiselSel(&netupg_item_tcpip_type);

	// get url type
	net_remote_cfg.url_type = OSD_GetMultiselSel(&netupg_item_url_type);
	
	// get url
	value = OSD_GetEditFieldContent(&netupg_item_url);
	if(net_remote_cfg.url_type == 0)
		net_remote_cfg.url_int = htonl(value);
	else
		ComUniStrToAsc((UINT8 *)value,net_remote_cfg.url_str);

	// get user name
	value = OSD_GetEditFieldContent(&netupg_item_user);
	ComUniStrToAsc((UINT8*)value, net_remote_cfg.user);

	// get user password
	value = OSD_GetEditFieldContent(&netupg_item_pwd);
	ComUniStrToAsc((UINT8*)value, net_remote_cfg.pwd);
}

//static LIB_NUC lib_nuc;
static UINT32 net_ui_callback(UINT32 type, UINT32 code)
{
	ap_send_msg(type, code, FALSE);	
	return 0;
}

static UINT32 net_user_stop()
{
}


static generate_url(char *url)
{
	UINT32 value;
	int pos;

	win_get_netupg_param();
	
	if (net_remote_cfg.protocol_type == 0)
	{        
        if (net_remote_cfg.url_type == 0)
        {
            UINT8 *ptr = (UINT8 *)&net_remote_cfg.url_int;
            sprintf(url, "http://%d.%d.%d.%d/", ptr[0], ptr[1], ptr[2], ptr[3]);
        }
        else
        {
		    sprintf(url, "http://%s/", net_remote_cfg.url_str);
        }
	}
	else
	{
        sprintf(url, "ftp://%s:%s@", net_remote_cfg.user,
                                     net_remote_cfg.pwd);
		if (net_remote_cfg.url_type == 0)
        {
            char tmp_string[32];
            UINT8 *ptr = (UINT8 *)&net_remote_cfg.url_int;
            sprintf(tmp_string, "%d.%d.%d.%d/", ptr[0], ptr[1], ptr[2], ptr[3]);
            strcat(url, tmp_string);
        }
        else
        {            
		    strcat(url, net_remote_cfg.url_str);
            strcat(url, "/");
        }	
	}
}

static UINT32 netupg_download_configfile()
{
    UINT32 handle;
	char *url = MALLOC(1024);
    
    if (url == NULL)
    {
        win_netupg_msg_update("No enough memory! Download failed!");
        download_started = 0;
        return 0;
    }
    else
    {
        //sprintf(url, "/%s to be downloaded...", DEFULT_CONFIG_FILE);
        win_netupg_msg_update("start to download config file...");
    }

	generate_url(url);
	if(network_performance_test==1)
	{
    	strcat(url, "test_download.bin");
        handle = libnet_perform_test(url, buffer_for_cfgfile, buflen_for_cfgfile, 0);
	}
    else
    {
    	strcat(url, DEFULT_CONFIG_FILE);
    	net_file_type = 0; // config file
        handle = libnet_download_to_mem(url, buffer_for_cfgfile, buflen_for_cfgfile, 0);
    }    
	FREE(url);
    return handle;
}

static UINT32 netupg_download_upgradefile(const char *file)
{
    UINT32 handle;
	char *url = MALLOC(1024);

    if (url == NULL)
    {
        win_netupg_msg_update("No enough memory! Download failed!");
        download_started = 0;
        return 0;
    }
    else
    {
        //sprintf(url, "/%s to be downloaded...", file);
        win_netupg_msg_update("start to download firmware...");
    }
    
	generate_url(url);
	strcat(url, file);
	net_file_type = 1; // upgrade abs file
	handle = libnet_download_to_mem(url, buffer_for_upgradefile, buflen_for_upgradefile, 0);
    
	FREE(url);
    return handle;
}

//call the C library funtion to split the string	
static char *_strsep(char **stringp, const char *delim)
{
	register char *tmp = *stringp;
	register char *tmp2 = tmp;
	register const char *tmp3;
	if (!*stringp) return 0;
	for (tmp2 = tmp; *tmp2; ++tmp2)
	{
		for (tmp3 = delim; *tmp3; ++tmp3)
			if (*tmp2 == *tmp3)
			{	/* delimiter found */
				*tmp2 = 0;
				*stringp = tmp2 + 1;
				return tmp;
			}
	}
	*stringp = 0;
	return tmp;
}

static int calc_version(const char *sver)
{
	int v = 0;
	int field = 0;
	int len = STRLEN((char *)sver);
	int i;

	//follow the "xx.xx.xx" format
	for(i = 0; i < len; i++)
	{
		if((sver[i] >= '0') && (sver[i] <= '9'))
		{
			field = field * 10 + sver[i] - '0'; 

			if(field > 99)
			{
				return 0;
			}
		}
		else if (sver[i] == '.')
		{
			v = v * 100 + field;
			field = 0;
		}
		else
		{
			//illegal character
			return 0;
			
		}
	}

	v = v * 100 + field;
	return (v > 999999 ? 0 : v);	
}


static int check_config_item(char *line, char **sver, char **sfile, const char *model)
{
	int i;
	char *sitems[] = {NULL, NULL, NULL, NULL}; /* model, version, file */

	i = 0;
	char *token = _strsep(&line, ";");
	while(token)
	{
		sitems[i++] = token;
		if(i == 3)
			break;
		token = _strsep(&line, ";");
	}

	if(i != 3)
	{
		//not enough field, return 0
		return 0;		
	}

	//split the STB model version
	//1=35001-01001
	char *s = sitems[0];
	token = _strsep(&s, "=");
	if(token == 0)
	{
		//not follow the format 
		return 0;
	}
	//check with the ver in bootloader
	/*
	CHUNK_HEADER blk_header;
	unsigned long id = 0;
	sto_chunk_goto(&id, 0, 1);
	sto_get_chunk_header(id, &blk_header);
	*/
	
	libc_printf("STB module = %s\n", s);
	libc_printf("version = %s, %d\n", sitems[1], calc_version(sitems[1]));
	libc_printf("file = %s\n", sitems[2]);
	libc_printf("model version = %s\n", model);
	
	if(STRCMP(s, (char *)model) != 0)
	{
		//not for the model
		return 0;
	}

	if(sver) 
		*sver =  sitems[1];
	if(sfile) 
		*sfile = sitems[2];
	
	return 1;
}

static int check_config_file(char *buffer, int len)
{
	//firstly split with "\r\n"
	char *line;
	int ver = 0, maxver;
	
	char *sfile = NULL;
	char *stmpfile = NULL;
	char *sver = NULL, *stmpver = NULL;
	char *ptr = buffer;

    CHUNK_HEADER chunk_hdr;
    UINT32 id;

	if (len <= 0)
	{
        win_netupg_msg_update("No valid firmware!");
        download_started = 0;
		return -1;
    }
	
    /* get version in bootloader */
    id = 0;
    sto_chunk_goto(&id, 0, 1);
    sto_get_chunk_header(id, &chunk_hdr);

	maxver = 0;	
	line = _strsep(&ptr, "\n");
	while(line != NULL)
	{		
		//split the items
		if(0 !=  check_config_item(line, &stmpver, &stmpfile, chunk_hdr.version))
		{
			ver = calc_version(stmpver);
			
			if(maxver < ver)
			{
				maxver = ver;
				sver = stmpver;
				sfile = stmpfile;
				
			}
		}
		line = _strsep(&ptr, "\n");
	}

	if (sfile)
	{
#define MAINCODE_CHUNK_ID   0x01FE0101

        id = MAINCODE_CHUNK_ID;
        sto_get_chunk_header(id, &chunk_hdr);

        libc_printf("current version = %s\n", chunk_hdr.version);
		libc_printf("upgrade version = %s\n", sver);
		libc_printf("upgrade file = %s\n", sfile);

        UINT8 back_saved;
        win_popup_choice_t choice;
        int burnflash_ret;
        char tmp[256];
        
        win_compopup_init(WIN_POPUP_TYPE_OKNO);
#if 0        
        sprintf(tmp, "Current firmware version: %s", chunk_hdr.version);
        win_netupg_msg_update(tmp);
        sprintf(tmp, "Newest firmware version: %s", sver);
        win_netupg_msg_update(tmp);
        sprintf(tmp, "Are you sure to download the newest firmware?"); 
#else        
        sprintf(tmp, "Current firmware version: %s\n"
                     "Newest firmware version: %s\n\n"
                     "download the newest one?",
                     chunk_hdr.version, sver);
#endif
    	win_compopup_set_msg(tmp, NULL, 0);        
    	win_compopup_set_default_choice(WIN_POP_CHOICE_YES);
    	choice = win_compopup_open_ext(&back_saved);
    	if (choice == WIN_POP_CHOICE_YES)
    	{
            upgrade_handle = netupg_download_upgradefile(sfile);
    	}
        else
        {
            win_netupg_msg_update("No firmware to be downloaded.");
            download_started = 0;
        }
	}
    else
    {
        win_netupg_msg_update("No valid firmware!");
        download_started = 0;
    }

	return 0;

}

static int check_upgrade_file(unsigned char* buffer, int buf_len )
{
	UINT32 i;
	UINT32 data_id;
	UINT32 data_len;
	UINT32 data_off;
	UINT32 data_crc;
	UINT32 crc;
	UINT32 pointer = 0;
	struct sto_device *flash_dev;

	if (buf_len <= 0)
		return -1;
	
	if ((flash_dev = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0)) == NULL)
	{
		return -1;
	}

#define FETCH_LONG(p)  ((((*(p)) << 24)) | ((*(p + 1)) << 16) | ((*(p + 2)) << 8) | (*(p + 3)))
	do
	{
		data_id  = FETCH_LONG(buffer + pointer + CHUNK_ID);
		data_len = FETCH_LONG(buffer + pointer + CHUNK_LENGTH);
		data_off = FETCH_LONG(buffer + pointer + CHUNK_OFFSET);
		data_crc = FETCH_LONG(buffer + pointer + CHUNK_CRC);

		if (pointer != 0)
		{
			if ((data_id >> 16) & 0xFF + (data_id >> 24) & 0xFF != 0xFF)
				return 1;
		}

		if (data_off >(UINT32)(flash_dev->totol_size))
		{
			libc_printf("@pointer[%08X] id[%08X] data_off[%08X] > flash size\n", \
				pointer, data_id, data_off);
			return 2;
		}
		if ((data_off != 0) && (data_len > data_off))
		{
			libc_printf("@pointer[%08X] id[%08X] data_len[%08X] > data_off[%08X]\n", \
				pointer, data_id, data_len, data_off);
			return 3;
		}
		if (data_crc != NO_CRC)
		{
			crc = MG_Table_Driven_CRC(0xFFFFFFFF, buffer + pointer + 16, data_len);
			if (data_crc != crc)
			{
				libc_printf("@pointer[%08X] id[%08X] crc[%08X] != data_crc[%08X]\n", \
					pointer, data_id, crc, data_crc);
				return 4;
			}
		}
		pointer += data_off;
		if (pointer + CHUNK_HEADER_SIZE >(UINT32)(flash_dev->totol_size))
		{
			libc_printf("@pointer[%08X] no space for header\n", pointer);
			return 5;
		}
	
	} while (data_off);

	libc_printf("the upgrade file passed check!\n");
    return 0;
}


static void netupg_start()
{
    INT32 vscr_idx = osal_task_get_current_id();
    lpVSCR apVscr = OSD_GetTaskVscr(vscr_idx);

	// get current upgrade parmeters.
	win_get_netupg_param();
	
	// save current setting
	set_remote_ip_cfg(&net_remote_cfg);

    win_netupg_process_update(0);
    win_netupg_msg_clear();
    OSD_UpdateVscr(apVscr);
    
	IP_LOC_CFG local_cfg;
    libnet_get_ipconfig(&local_cfg);
    if ((ntohl(local_cfg.ip_addr) & 0xFF000000) == 0)
    {
        win_netupg_msg_update("Invalid local IP address!");
        OSD_UpdateVscr(apVscr);
        download_started = 0;
        return;
    }

	if (net_remote_cfg.url_type == 0 &&
		(ntohl(net_remote_cfg.url_int) & 0xFF000000) == 0)
	{
		win_netupg_msg_update("Invalid server IP address!");
		OSD_UpdateVscr(apVscr);
		OSD_ContainerChgFocus(&g_win_netupg, IDC_NETUPG_URL,
							  C_DRAW_SIGN_EVN_FLG | C_UPDATE_FOCUS);
		download_started = 0;
		return;
	}
    
    /* download config file */
    upgrade_handle = netupg_download_configfile(); /* it will download upgrade file */
    return;

#if 0	
	// ...
	MEMCPY(&lib_nuc.local_cfg, &local_cfg, sizeof(local_cfg));
	MEMCPY(&lib_nuc.rmt_cfg, &net_remote_cfg, sizeof(net_remote_cfg));
	lib_nuc.pfn_ui_connect = net_ui_callback;
	lib_nuc.pfn_user_stop = net_user_stop;
	lib_nuc.file_addr = __MM_PVR_VOB_BUFFER_ADDR;
	lib_nuc.file_len = 0x400000;
	lib_net_upg_start(&lib_nuc);
#endif	
}

static void net_mi_callback(UINT8* string)
{
}
/*******************************************************************************
*   key mapping and event callback definition
*******************************************************************************/
#define VACT_ABORT (VACT_PASS + 1)
#define VACT_BLUE  (VACT_PASS + 2)

static VACTION netupg_item_sel_keymap(POBJECT_HEAD pObj, UINT32 key)
{
    VACTION act = VACT_PASS;

    switch(key)
    {
    case V_KEY_LEFT:
        act = VACT_DECREASE;
        break;
    case V_KEY_RIGHT:
        act = VACT_INCREASE;
        break; 
    case V_KEY_ENTER:
        act = VACT_ENTER;
        break; 
    default:
        break;
    }

    return act; 
}

static PRESULT netupg_item_sel_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
	UINT8 bID = OSD_GetObjID(pObj);

    switch(event)
    {
    case EVN_POST_CHANGE:
		if(IDC_NETUPG_URL_TYPE == bID)
		{
			net_remote_cfg.url_type = param1;
			// change the display of url;
			netupg_set_url(TRUE);
		}
		else if (IDC_NETUPG_TYPE == bID)
		{
			netupg_sel_protocol(param1, TRUE);
			net_remote_cfg.protocol_type = param1;
		}
        break; 
	default:
		break;
    }
    return ret;
}

static VACTION netupg_item_con_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	switch(key)
	{
	case V_KEY_ENTER:     
		act = VACT_ENTER;
		break;     
    case V_KEY_YELLOW:
        act = VACT_ABORT;
        break;
    case V_KEY_BLUE:
        act = VACT_BLUE;
        break;
	default:
		act = VACT_PASS;
	}

	return act;
}

static PRESULT netupg_item_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    VACTION unact;
	UINT8 bID = OSD_GetObjID(pObj);

	switch(event)
	{
	case EVN_UNKNOWN_ACTION:
		unact = (VACTION)(param1 >> 16);
        if ((unact == VACT_ABORT) && (download_started == 1))
        {
            libnet_download_abort(upgrade_handle);
            upgrade_handle = 0;
            download_started = 0;
            win_netupg_msg_update("User abort!");
        }
        if ((bID == IDC_NETUPG_START) &&(unact == VACT_ENTER) && (download_started == 0))
        {
            download_started = 1;
		    netupg_start();
        }
        else if(unact == VACT_BLUE)
        {
            download_started = 1;
            network_performance_test = 1;
		    netupg_start();
            network_performance_test =0;
        }
        
		break;
	default:
		break;
	}
    return ret;
}

static VACTION  netupg_item_edf_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	
	switch(key)
    {
	case V_KEY_0:	case V_KEY_1:	case V_KEY_2:	case V_KEY_3:
	case V_KEY_4:	case V_KEY_5:	case V_KEY_6:	case V_KEY_7:
	case V_KEY_8:	case V_KEY_9:
		act = key - V_KEY_0 + VACT_NUM_0;
		break;
	case V_KEY_LEFT:
		act = VACT_EDIT_LEFT;
		break;
	case V_KEY_RIGHT:
		act = VACT_EDIT_RIGHT;
		break;		
	case V_KEY_RED:
		act = VACT_CAPS;
		break;
	case V_KEY_GREEN:
		act = VACT_DEL;
		break;
		
	default:					
		act = VACT_PASS;
	}

	return act;	 
}

static PRESULT  netupg_item_edf_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
	PRESULT ret = PROC_PASS;
	UINT8 bID;
	UINT8 status;
	EDIT_FIELD* edf;
	UINT8 back_save;
	UINT32 value;

	bID = OSD_GetObjID(pObj);

	edf = (EDIT_FIELD*)pObj;
	//libc_printf("pObj=%xh, event=%x, param1=%x, param2=%x\n",pObj, event, param1, param2);

	switch(event)
	{
	case EVN_KEY_GOT:
		if((bID == IDC_NETUPG_URL && net_remote_cfg.url_type != 0) || 
			bID == IDC_NETUPG_USER ||
			bID == IDC_NETUPG_PASSWORD) 
			ret = mobile_input_proc(edf,(VACTION)(param1>>16), param1 & 0xFFFF, param2);
		break;
		
	case EVN_PRE_CHANGE:
		break;
	case EVN_POST_CHANGE:
		//libc_printf("POST: ip %xh, get value = %xh\n",param1,OSD_GetEditFieldContent((PEDIT_FIELD)pObj));
		break;

	case EVN_FOCUS_PRE_GET:
	case EVN_PARENT_FOCUS_PRE_GET:
		netupg_mobile_input_init(bID);
		break;

	case EVN_FOCUS_PRE_LOSE:
	case EVN_PARENT_FOCUS_PRE_LOSE:	
		
		//netupg_mobile_input_init(bID);
		break;		

	case EVN_DATA_INVALID:		
		win_compopup_init(WIN_POPUP_TYPE_OK);
        win_compopup_set_msg("Invalid address number!", NULL, 0);
		win_compopup_open_ext(&back_save);
		ret = PROC_LOOP;
		break;
		
	}

	return ret;
}

static VACTION netupg_con_keymap(POBJECT_HEAD pObj, UINT32 key)
{
    VACTION act;
    
    switch(key)
    {
    case V_KEY_UP:
        act = VACT_CURSOR_UP;
        break;
    case V_KEY_DOWN:
        act = VACT_CURSOR_DOWN;
        break;      
    case V_KEY_EXIT:
    case V_KEY_MENU:
        act = VACT_CLOSE;
        break;
    default:    
        act = VACT_PASS;
        break;
    }

    if (download_started == 1)
    {
        act = VACT_PASS;
    }
    
    return act;
}

static PRESULT netupg_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    VACTION unact;

    switch(event)
    {
    case EVN_PRE_OPEN:
        wincom_open_title((POBJECT_HEAD)&g_win_netupg,RS_NET_UPGRADE, 0);
		netupg_init();
        win_netupg_msg_clear();
        download_started = 0;
        upgrade_handle = 0;
        break;
	case EVN_POST_OPEN:
		wincom_open_help(pObj,netupg_helpinfo , ARRAY_SIZE(netupg_helpinfo));
		break;		
    case EVN_PRE_CLOSE:
		win_get_netupg_param();
		set_remote_ip_cfg(&net_remote_cfg);
        sys_data_save(1);
		wincom_close_help();
        /* Make OSD not flickering */
        *((UINT32*)param2) &= ~C_CLOSE_CLRBACK_FLG; 
        break;
	case EVN_POST_CLOSE:
		netupg_block_free();
        break;
	case EVN_MSG_GOT:		
		ret = netupg_msg_proc(param1,param2);
		break;
    default:
        break;
    }

    return ret; 
}


/*******************************************************************************
*   other functions  definition
*******************************************************************************/

#ifdef CI_PLUS_SUPPORT
static BOOL netupg_allcode_check(UINT8 *pbuff, UINT32 length)
{
	struct sto_device *flash_dev = NULL;
	UINT32 chunk_id = 0xFFFFFFFF;
	CHUNK_HEADER chunk_header;
	UINT8 *data_addr = NULL;
	UINT32 data_len = 0;
	BOOL ret = TRUE;

	if (NULL == pbuff || 0 == length)
	{
		ASSERT(0);
		return FALSE;
	}

	chunk_init(pbuff, length);	
	// step 2: maincode check
	// get maincode raw data address & length	
	chunk_id = MAINCODE_ID;
	if(!get_chunk_header(chunk_id, &chunk_header))
	{
		ret = FALSE;		
		return ret;
	}
	data_addr = chunk_goto(&chunk_id, 0xFFFFFFFF, 1) + CHUNK_HEADER_SIZE;
	data_len = chunk_header.len - CHUNK_HEADER_SIZE + CHUNK_NAME;
	
	if (0 != Test_RSA_Ram((UINT32)data_addr, data_len)) // this function operate RAW Data and RAW length
	{
		ret = FALSE;
		return ret;
	}

	// step 3: seecode check
	// get raw data address & length from memory
	chunk_id = SEECODE_ID;
	if (!get_chunk_header(chunk_id, &chunk_header))
	{
		ret = FALSE;
		return ret;
	}
	data_addr = chunk_goto(&chunk_id, 0xFFFFFFFF, 1) + CHUNK_HEADER_SIZE;
	data_len = chunk_header.len - CHUNK_HEADER_SIZE + CHUNK_NAME;
	if (0 != Test_RSA_Ram((UINT32)data_addr, data_len))
	{
		ret = FALSE;
		return ret;
	}

	return ret;
}
#endif

static PRESULT	netupg_msg_proc(UINT32 msg_type, UINT32 msg_code)
{
	PRESULT ret = PROC_LOOP;
	//libc_printf("Enter %s....\n",__FUNCTION__);	
	char msg[128];

    INT32 vscr_idx = osal_task_get_current_id();
    lpVSCR apVscr = OSD_GetTaskVscr(vscr_idx);
    int validUpgradeFile = 0;

	switch(msg_type)
	{
	case CTRL_MSG_SUBTYPE_CMD_SCAN:
		OSD_SetProgressBarPos(&netupg_bar_progress, msg_code);
		OSD_DrawObject((POBJECT_HEAD)&netupg_bar_progress,C_UPDATE_ALL);
		if(msg_code == 100)
		{
			UINT8 back_saved;
			win_popup_choice_t choice;
			win_compopup_init(WIN_POPUP_TYPE_OKNO);
			win_compopup_set_msg(NULL, NULL, RS_USBUPG_SURE_BURN_FLASH);
			choice = win_compopup_open_ext(&back_saved);
			if(choice == WIN_POP_CHOICE_YES)
			{
				//burning flash
				msg_code = 0;
				while(1)
				{
					msg_code+=5;					
					if(msg_code >= 100)
						break;
					OSD_SetProgressBarPos(&netupg_bar_progress, msg_code);
					OSD_DrawObject((POBJECT_HEAD)&netupg_bar_progress,C_UPDATE_ALL);					
					osal_task_sleep(300);
				}
				
			}
			
		}
		break;

    case CTRL_MSG_SUBTYPE_STATUS_DOWNLOAD_START:
        win_netupg_process_update(0);
        net_file_length = msg_code;
        sprintf(msg, "file length = %d bytes", msg_code);
        win_netupg_msg_update(msg);
        OSD_UpdateVscr(apVscr);
        break;
        
    case CTRL_MSG_SUBTYPE_STATUS_DOWNLOAD_PROGRESS:
		if (net_file_length == 0)
		{
			win_netupg_process_update(100);
		}
		else
		{
	        win_netupg_process_update(msg_code * 100 / net_file_length);
		}
        OSD_UpdateVscr(apVscr);
        break;
		
    case CTRL_MSG_SUBTYPE_STATUS_DOWNLOAD_FINISH:
        upgrade_handle = 0;
        if((int)msg_code >= 0)
        {
            int bar_pos = OSD_GetProgressBarPos(&netupg_bar_progress);
            if (bar_pos == 100)
            {
                sprintf(msg, "download finished! length = %d bytes", msg_code);
            }
            else
            {
                sprintf(msg, "download abort! length = %d bytes", msg_code);
            }
            win_netupg_msg_update(msg);
            OSD_UpdateVscr(apVscr);
            
            unsigned char *buffer;
            if(net_file_type == 0)
                buffer = buffer_for_cfgfile;
            else
                buffer = buffer_for_upgradefile;

            /*
            unsigned char md5[17];
            int i;
            md5_do_data(md5, buffer, msg_code);

            for(i = 0; i < 16; i++)
            {
                libc_printf("%x", md5[i]);
            }
            libc_printf("\n");
            */

            if(net_file_type == 0)
            {
				if (bar_pos == 100)
				{
	                buffer_for_cfgfile[msg_code] = 0;
	                win_netupg_process_update(0);                
	                win_netupg_msg_clear();
	                OSD_UpdateVscr(apVscr);

	                win_netupg_msg_update("Checking configuration file..");
	                check_config_file(buffer_for_cfgfile, msg_code);
	                OSD_UpdateVscr(apVscr);
				}
				else
				{
					download_started = 0;
				}
            }
            else
            {
                libc_printf("check upgrade file!\n");
                if (bar_pos == 100)
                {
					if (check_upgrade_file(buffer_for_upgradefile, msg_code) == 0)
					{
                    	validUpgradeFile = 1;
					}
					else
					{
						win_netupg_msg_update("Invalid firmware!");
	                	OSD_UpdateVscr(apVscr);
						download_started = 0;
					}
                }
                else
                {
                    download_started = 0;
                }
            }
        }
        else
        {
            switch (-msg_code)
            {
                case NET_ERR_CONNECT_FAILED:
                    STRCPY(msg, "Connect to server failed!");
                    break;
                case NET_ERR_USER_ABORT:
                    STRCPY(msg, "User abort!");
                    break;
                case NET_ERR_LOGIN_FAILED:
                    STRCPY(msg, "Invalid user or password, login failed!");
                    break;
                /*    
                case NET_ERR_FILE_NOT_FOUND:
                case NET_ERR_HTTP_SERVER_ERROR:
                case NET_ERR_FTP_SERVER_ERROR:
                case NET_ERR_OPERATION_NOT_PERMIT:
                case NET_ERR_FILE_SAVE_ERROR:
                */
                default:
                    STRCPY(msg, "Download failed!");
                    break;
            }
            win_netupg_msg_update(msg);
            OSD_UpdateVscr(apVscr);
            download_started = 0;
        }            

        /* update firmware */
        if (validUpgradeFile)
        {
            UINT8 back_saved;
            win_popup_choice_t choice;
            int burnflash_ret = -1;
            
            win_compopup_init(WIN_POPUP_TYPE_OKNO);
        	win_compopup_set_msg("Are you sure to burn the firmware?", NULL, 0);
        	win_compopup_set_default_choice(WIN_POP_CHOICE_NO);
        	choice = win_compopup_open_ext(&back_saved);
        	if (choice == WIN_POP_CHOICE_YES)
        	{
                win_get_netupg_param();
        		set_remote_ip_cfg(&net_remote_cfg);
                sys_data_save(1);
        
                win_netupg_process_update(0);
				win_netupg_msg_update("Burning flash, don't power off.");
				OSD_UpdateVscr(apVscr);

                ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_POOLING);
              //  osal_task_dispatch_off();
                sto_flash_disable_protect();
				netupg_set_upgrade_bloader_flag(1);
#ifdef CI_PLUS_SUPPORT				
				if (TRUE == netupg_allcode_check(buffer_for_upgradefile, msg_code))
				{
					netupg_set_upgrade_bloader_flag(0); // skip bootloader
#endif					
                	burnflash_ret = netupg_allcode_burn(buffer_for_upgradefile, msg_code, win_netupg_process_update);
#ifdef CI_PLUS_SUPPORT
				}
#endif				
				OSD_UpdateVscr(apVscr);
         //       osal_task_dispatch_on();
                ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_INTERRUPT);

                if(burnflash_ret == 0)
				{
                    download_started = 0;
        			key_pan_display("OFF ",4);
        			osal_task_sleep(500);
        			power_off_process(0);
                    
                    sys_data_factroy_init();
    			    sys_data_set_factory_reset(TRUE);
    			    sys_data_set_cur_chan_mode(TV_CHAN);
                        
        			power_on_process();
				}
				else
				{
                    download_started = 0;
					win_netupg_msg_update("Burning flash error!");
                    OSD_UpdateVscr(apVscr);
				}
        	}
            else
            {
                download_started = 0;
            }
        }
        break;
	}

	//libc_printf("Exit %s....\n",__FUNCTION__);

	return ret;
}

#endif /* NETWORK_SUPPORT */

#ifdef _INVW_JUICE   
int INVIEW_OADupgrade_flashwrite(unsigned char* buffer, int buf_len)
{
	int burnflash_ret;
		ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_POOLING);
      //  osal_task_dispatch_off();
        sto_flash_disable_protect();
		netupg_set_upgrade_bloader_flag(1);

		burnflash_ret = netupg_allcode_burn(buffer, buf_len, win_netupg_process_update); //added 0 to disable progress bar display

 //       osal_task_dispatch_on();
        ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_INTERRUPT);

        if(burnflash_ret == 0)
		{
        	download_started = 0;
			key_pan_display("OFF ",4);
			osal_task_sleep(500);
			power_off_process();
            sys_data_factroy_init();
		    sys_data_set_factory_reset(TRUE);
		    sys_data_set_cur_chan_mode(TV_CHAN);
			power_on_process();
			return 1;
		}
		else
		{
			printf("BURNING FLASH - OAD UPRGADE FAILED - SORRY - ERROR %d\n", burnflash_ret);
			return 0;
		}

}
#endif
